import './index.less'
import React, { useEffect, useRef, useState } from 'react'
import { Empty, Input, message, Space, Tree, TreeProps, Typography } from 'antd'
import { SearchOutlined } from '@ant-design/icons'
interface IProps {
  title?: string
  subTitle?: string
  routeList: IRoutesType[]
  leftKeys: string[]
  rightKeys: string[]
  onChange: (menuKey: string[], functionKey: string[]) => void
}

const getKeyValue = (treeData: IRoutesType[], allIds: any = {}): any => {
  treeData?.forEach((item) => {
    allIds[item.id] = []
    if (Array.isArray(item.children) && item.children.length > 0) {
      const ids = item.children?.map((it) => it.id + '')
      allIds[item.id] = ids
      getKeyValue(item.children, allIds)
    }
  })
  return allIds
}

const checkHasFunctionAndHandle = (
  treeData: IRoutesType[],
  result: Record<string, string[]> = {},
  leftIds: string[] = [],
  rightIds: string[] = [],
) => {
  treeData?.forEach((item) => {
    result[item.id] = []
    if (item.function && item.function.length > 0) {
      const leftId = item.id + ''
      const rightId = item.function?.map((it) => it.id + '')
      leftIds.push(leftId)
      rightIds.push(...rightId)
      result[item.id] = rightId
    }
    if (Array.isArray(item.children) && item.children.length > 0) {
      checkHasFunctionAndHandle(item.children, result, leftIds, rightIds)
    }
  })
  return { result, leftIds, rightIds }
}

const deepFilterChild = (treeData: IRoutesType[], keyword: string): IRoutesType[] => {
  return treeData?.reduce((acc: IRoutesType[], item) => {
    if (item.name.indexOf(keyword) > -1) {
      acc.push(item)
    }
    if (item.children && item.children.length > 0) {
      const filteredChildren = deepFilterChild(item.children, keyword)
      if (filteredChildren.length > 0) {
        // 如果 children 中有匹配的节点，将当前 item（包括其 children）添加到结果中
        const itemWithFilteredChildren = { ...item, children: filteredChildren }
        acc.push(itemWithFilteredChildren)
      }
    }
    return acc
  }, [])
}

const getOnlyIds = (treeData: IRoutesType[], allIds: string[] = []) => {
  treeData?.forEach((item) => {
    if (Array.isArray(item.children) && item.children.length > 0) {
      allIds.push(item.id + '')
      getOnlyIds(item.children, allIds)
    }
  })
  return allIds
}
/**
 *
 * @param fatherToChildren 是left所有father和child ID的映射 { 28:[29,30,31,32], 35:[36] } 是因为后端需要选中的item的fatherId 所以需要一个映射用于数据变化时将fatherId添加进去传到父组件 同时fatherId需要去重
 * @param mykeyvalue 是所有child中带function数组的ID映射 { 29:[37,38,39,40], 30:[42,43,44,45] } 是用来记录的，同时根据mykeyvalue判断当右面取消勾选或者勾选时左边是否联动
 * @function handleInitmykeyvalue 初始化mykeyvalue 根据leftkeys和rightkeys形成映射关系用于编辑状态下数据回填展示
 * @param treeLeftRef 记录left结构用于搜索重置
 * @param funcTreeRef 记录right结构用于搜索重置
 */

export default function TransferTree(props: IProps) {
  const routeList = useRef<any>()
  // console.log(props.routeList, 'props.routeList')
  const [treeData, setTreeData] = useState<IRoutesType[]>([])
  const fatherToChildren = getKeyValue(props.routeList)
  const onlyFatherIds = getOnlyIds(props.routeList)
  // console.log(fatherToChildren, 'fatherToChildren', onlyFatherIds)
  const [leftKeys, setLeftKeys] = useState<string[]>([])
  const [rightKeys, setRightKeys] = useState<string[]>([])
  const [funcTree, setFuncTree] = useState<IRoutesType[]>([])
  const funcTreeRef = useRef<any>()
  const mykeyvalue = useRef<Record<string, string[]>>({})
  const [isChange, setIsChange] = useState(false)
  const treeLeftRef = useRef<any>(null)
  useEffect(() => {
    const right = props.rightKeys?.map((it) => it + '')
    const left = props.leftKeys?.map((it) => it + '')?.filter((item) => !onlyFatherIds?.includes(item))
    setLeftKeys(left)
    setRightKeys(right)
    routeList.current = props.routeList
    setTreeData(props.routeList)
    handleInitmykeyvalue(left, right)
  }, [props.leftKeys, props.rightKeys, props.routeList])
  const handleInitmykeyvalue = (left: string[], right: string[]) => {
    // result是所有所有所有所有的id包含function的映射
    const { result } = checkHasFunctionAndHandle(routeList.current)
    // console.log(result, routeList.current, 'result')
    left?.forEach((id) => {
      mykeyvalue.current[id] = []
      Object.keys(result).forEach((k) => {
        right.forEach((r) => {
          if (id == k && result[k]?.includes(r)) {
            mykeyvalue.current[id] = [...new Set([...mykeyvalue.current[id], r])]
          }
        })
      })
    })
    // console.log(mykeyvalue, 'mykeyvalue')
  }

  const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.value === '') {
      setTreeData(routeList.current)
    } else {
      const data = deepFilterChild(routeList.current, e.target.value)
      setTreeData(data)
    }
  }
  const handleSearchRight = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.value === '') {
      setFuncTree(funcTreeRef.current)
    } else {
      const data = funcTreeRef.current?.filter((item: any) => item.name.indexOf(e.target.value) > -1)
      setFuncTree(data)
    }
  }
  useEffect(() => {
    // console.log(mykeyvalue.current, 'mykeyvalue.current')
    const halfFatherIds = [] as string[]
    Object.keys(fatherToChildren)?.forEach((key) => {
      Object.keys(mykeyvalue.current)?.forEach((k) => {
        if (mykeyvalue.current[k]?.length > 0 && fatherToChildren[key].includes(k)) {
          halfFatherIds.push(key)
        }
      })
    })
    const halfChecked = [...[...new Set(halfFatherIds)]]
    // console.log([...new Set(leftKeys), ...halfChecked], [...rightKeys], '123990')
    props.onChange && props.onChange([...new Set(leftKeys), ...halfChecked], [...rightKeys])
  }, [isChange])
  const onRouteCheck = (checkedKeysValue: any, event: any) => {
    if (event.node.parentId == 0 && event.node?.children && event.node?.children?.length > 0) {
      return
    }
    if (event.node.function && event.node.function.length > 0) {
      setLeftKeys(checkedKeysValue as string[])
      const rightIds = event.node.function?.map((it: any) => it.id + '')
      if (event.checked) {
        mykeyvalue.current[event.node.id] = rightIds
        setRightKeys([...rightKeys, ...rightIds])
        setIsChange(!isChange)
      } else {
        const resetRightIds = rightKeys?.filter((it) => !rightIds.includes(it))
        mykeyvalue.current[event.node.id] = []
        setIsChange(!isChange)
        setRightKeys(resetRightIds)
      }
    } else {
      message.warning('该菜单未配置对应的功能权限！')
    }
  }
  const handleRouteSelect: any = (_: React.Key, event: any) => {
    if (event.selected) {
      const funcTree = event.node?.['function'] || []
      setFuncTree(funcTree)
      funcTreeRef.current = funcTree
    }
  }

  const onFuncCheck: any = (_: React.Key, event: any) => {
    const parentId = event.node.parentId + ''
    const selfId = event.node.id + ''
    // console.log(event, 'event1')
    // console.log(parentId, 'event1')
    // console.log(mykeyvalue.current[parentId], '12')
    if (event.checked) {
      if (!mykeyvalue.current[parentId]) mykeyvalue.current[parentId] = []
      const index = mykeyvalue.current[parentId].findIndex((it: any) => it == selfId)
      // console.log(index, 'aa')
      if (index === -1) {
        // 说明没有
        mykeyvalue.current[parentId].push(selfId)
      }
      setLeftKeys([...leftKeys, parentId])
      setRightKeys([...rightKeys, selfId])
      setIsChange(!isChange)
    } else {
      // console.log(mykeyvalue.current, parentId, 'mykeyvalue.current123123')
      // console.log(leftKeys, 'leftKeys123123')
      if (!mykeyvalue.current[parentId]) mykeyvalue.current[parentId] = []
      const index = mykeyvalue.current[parentId].findIndex((it: any) => it == selfId)
      // console.log(index, 'index123123')
      mykeyvalue.current[parentId].splice(index, 1)
      if (mykeyvalue.current[parentId].length === 0) {
        const leftIds = leftKeys?.filter((it) => it != parentId)
        // console.log([...leftIds], 'leftIds')
        setLeftKeys([...leftIds])
      }
      const rightIds = rightKeys?.filter((it) => it != selfId)
      setRightKeys([...rightIds])
      setIsChange(!isChange)
    }
  }

  return (
    <div className="treetransfer_wrap">
      <div className="tw_left">
        <div className="tw_header">
          <div className="twheader_title">{props.title ? props.title : '菜单权限'}</div>
          <div className="twheader_actions">
            <Space>
              <Typography.Link
                onClick={() => {
                  const { result, leftIds, rightIds } = checkHasFunctionAndHandle(treeData)
                  // console.log(result, 'result')
                  mykeyvalue.current = result
                  setIsChange(!isChange)
                  // console.log(rightIds, 'rightIds')
                  setLeftKeys([...leftIds])
                  setRightKeys([...rightIds])
                }}
              >
                全选
              </Typography.Link>
              <Typography.Link
                onClick={() => {
                  setLeftKeys([])
                  setRightKeys([])
                  mykeyvalue.current = {}
                  setIsChange(!isChange)
                }}
              >
                全不选
              </Typography.Link>
            </Space>
          </div>
        </div>
        <div className="tw_search_box">
          <Input
            placeholder="搜索菜单"
            prefix={<SearchOutlined style={{ color: '#999' }} />}
            className="search_input"
            onChange={handleSearch}
          />
        </div>
        {treeData && treeData.length > 0 ? (
          <Tree
            className="tw_tree"
            blockNode
            defaultExpandAll
            checkedKeys={leftKeys}
            treeData={treeData}
            onCheck={onRouteCheck}
            onSelect={handleRouteSelect}
            fieldNames={{ title: 'name', key: 'id', children: 'children' }}
            checkable
            ref={treeLeftRef}
          />
        ) : (
          <EmptyCom></EmptyCom>
        )}
      </div>
      <div className="tw_right">
        <div className="tw_header">
          <div className="twheader_title">{props.subTitle ? props.subTitle : '功能权限（角色组权限）'}</div>
          <div className="twheader_actions">
            <Space>
              <Typography.Link
                onClick={() => {
                  if (funcTree && funcTree.length === 0) return
                  const parentId = funcTree[0].parentId + ''
                  const ids = funcTree?.map((it) => it.id + '')
                  mykeyvalue.current[parentId] = ids
                  setLeftKeys([...leftKeys, parentId])
                  setRightKeys([...rightKeys, ...ids])
                  setIsChange(!isChange)
                }}
              >
                全选
              </Typography.Link>
              <Typography.Link
                onClick={() => {
                  if (funcTree && funcTree.length === 0) return
                  const parentId = funcTree[0].parentId + ''
                  const ids = funcTree?.map((it) => it.id + '')
                  mykeyvalue.current[parentId] = []
                  const leftIds = leftKeys?.filter((it) => it != parentId)
                  const rightIds = rightKeys?.filter((it) => !ids.includes(it))
                  setLeftKeys([...leftIds])
                  setRightKeys([...rightIds])
                  setIsChange(!isChange)
                }}
              >
                全不选
              </Typography.Link>
            </Space>
          </div>
        </div>
        <div className="tw_search_box">
          <Input
            placeholder="搜索功能"
            prefix={<SearchOutlined style={{ color: '#999' }} />}
            className="search_input"
            onChange={handleSearchRight}
          />
        </div>
        {funcTree && funcTree.length > 0 ? (
          <Tree
            className="tw_tree"
            blockNode
            checkable
            defaultExpandAll
            checkedKeys={rightKeys}
            treeData={funcTree}
            onCheck={onFuncCheck}
            fieldNames={{ title: 'name', key: 'id', children: 'children' }}
          />
        ) : (
          <EmptyCom></EmptyCom>
        )}
      </div>
    </div>
  )
}

const EmptyCom = () => {
  return (
    <Empty
      style={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
      }}
      image={Empty.PRESENTED_IMAGE_SIMPLE}
    />
  )
}
